package com.gjm.tool.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.poi.excel.ExcelReader;
import lombok.Data;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class XcTest {
    // 用于存储字段比较结果的缓存
    private static final Map<String, Boolean> fieldComparisonCache = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        test01();

    }

    /**
     * oracle和达梦字段、类型、长度比对
     */
    public static void test01() {
//        List<List<String>> entityOraList = ExcelUtil.readExcel("C:\\Users\\Administrator\\Desktop\\信创\\oracle数据库字段.xlsx", 0, Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7));
//        List<List<String>> entityDmList = ExcelUtil.readExcel("C:\\Users\\Administrator\\Desktop\\信创\\达梦字段.xlsx", 0, Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7));

//        List<List<String>> entityOraList = ExcelUtil.readExcel("C:\\Users\\Administrator\\Desktop\\信创\\oracle数据库字段.xlsx", 0, Arrays.asList(0));
        List<List<String>> entityDmList = ExcelUtil.readExcel("C:\\Users\\Administrator\\Desktop\\信创\\达梦字段.xlsx", 0, Arrays.asList(0));
        List<String> dmTableList = entityDmList.stream().map(i -> i.get(0)).collect(Collectors.toList());
        //1 对比表名
        System.out.println("开始");

        ExcelReader reader = cn.hutool.poi.excel.ExcelUtil.getReader("C:\\Users\\Administrator\\Desktop\\信创\\oracle数据库字段.xlsx");
        // 读取指定sheet页面，0表示第一个sheet
        List<List<Object>> sheetList = reader.read(0);
        // 关闭读取器，释放资源
        reader.close();
        for (List<Object> objects : sheetList) {
            if (!dmTableList.contains(getFieldValue(objects, 0))){
                System.out.println(getFieldValue(objects, 0));
            }
        }




        //oracle字段
//        List<BaseEntity> entityOraList = readAndConvertExcel("C:\\Users\\gjm\\Desktop\\oracle数据库字段.xlsx");
        //达梦字段
//        List<BaseEntity> entityDmList = readAndConvertExcel("C:\\Users\\Administrator\\Desktop\\信创\\达梦字段.xlsx");
//        // 2. 构建达梦数据的快速查找Map (O(1)查找)
//        Map<String, BaseEntity> dmMap = entityDmList.parallelStream()
//                .collect(Collectors.toConcurrentMap(
//                        BaseEntity::getField_1,
//                        Function.identity(),
//                        (existing, replacement) -> existing
//                ));

        // 3. 使用并行流进行快速比对
        // 分批处理示例（每批5万条）
        int batchSize = 5000;
//        for (int i = 0; i < entityOraList.size(); i += batchSize) {
//            List<BaseEntity> batch = entityOraList.subList(i, Math.min(i + batchSize, entityOraList.size()));
//            List<String> notExistList = batch.parallelStream()
//                    .filter(oraEntity -> {
//                        BaseEntity dmEntity = dmMap.get(oraEntity.getField_1());
//                        // 4. 使用缓存优化重复字段比较
//                        return dmEntity == null || !compareEntitiesWithCache(oraEntity, dmEntity);
//                    })
//                    .map(BaseEntity::getField_1)
//                    .collect(Collectors.toList());
//
//            // 5. 批量输出结果（减少IO操作）
//            System.out.println("差异字段数量: " + notExistList.size());
//            notExistList.forEach(System.out::println);
//        }
    }


    // 带缓存的实体比较方法
    private static boolean compareEntitiesWithCache(BaseEntity ora, BaseEntity dm) {
        String cacheKey = ora.getField_1() + ora.getField_2() + dm.getField_2(); // 简化的缓存键
        return fieldComparisonCache.computeIfAbsent(cacheKey, k ->
                Objects.equals(ora.getField_2(), dm.getField_2()) &&
                        Objects.equals(ora.getField_3(), dm.getField_3()) &&
                        Objects.equals(ora.getField_4(), dm.getField_4()) &&
                        Objects.equals(ora.getField_5(), dm.getField_5()) &&
                        Objects.equals(ora.getField_6(), dm.getField_6()) &&
                        Objects.equals(ora.getField_7(), dm.getField_7()) &&
                        Objects.equals(ora.getField_8(), dm.getField_8())
        );
    }

    private static List<BaseEntity> readAndConvertExcel(String filePath) {
        List<List<String>> rawList = readExcel(filePath, 0, Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7));

        // 跳过标题行并预分配大小
        List<List<String>> dataList = rawList.subList(1, rawList.size());

        // 使用并行流+预分配数组优化转换
        BaseEntity[] entities = new BaseEntity[dataList.size()];
        IntStream.range(0, dataList.size()).parallel().forEach(i -> {
            List<String> row = dataList.get(i);
            entities[i] = new BaseEntity();
            entities[i].setField_1(getFieldValue(row, 0));
            entities[i].setField_2(getFieldValue(row, 1));
            entities[i].setField_3(getFieldValue(row, 2));
            entities[i].setField_4(getFieldValue(row, 3));
            entities[i].setField_5(getFieldValue(row, 4));
            entities[i].setField_6(getFieldValue(row, 5));
            entities[i].setField_7(getFieldValue(row, 6));
            entities[i].setField_8(getFieldValue(row, 7));
        });

        return Arrays.asList(entities);
    }


    public static String getFieldValue(List list,Integer index) {
        String result = "";
        if (CollectionUtil.isNotEmpty( list) && list.size() > index){
            result = String.valueOf(list.get(index));
        }
        return result;
    }

    public static List<List<String>> readExcel(String filePath, int sheetNum, List<Integer> indexList) {
        List<List<String>> fieldList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(indexList)) {
            ExcelReader reader = cn.hutool.poi.excel.ExcelUtil.getReader(filePath);
            // 读取指定sheet页面，0表示第一个sheet
            List<List<Object>> sheetList = reader.read(sheetNum);
            // 关闭读取器，释放资源
            reader.close();
            for (List<Object> objects : sheetList) {
                List<String> list = new ArrayList<>();
                for (Integer index : indexList) {
                    list.add(getFieldValue(objects, index));
                }
                fieldList.add(list);
            }
        }
        return fieldList;
    }

    @Data
    static class BaseEntity {
        private String field_1;
        private String field_2;
        private String field_3;
        private String field_4;
        private String field_5;
        private String field_6;
        private String field_7;
        private String field_8;
        private String field_9;
        private String field_10;
    }
}
